package com.foreverwin.mes.warehouse.service.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.foreverwin.mes.common.enums.HandleEnum;
import com.foreverwin.mes.core.base.FrontPage;
import com.foreverwin.mes.core.exception.BusinessException;
import com.foreverwin.mes.core.utils.CommonMethods;
import com.foreverwin.mes.core.utils.DateUtil;
import com.foreverwin.mes.core.utils.StringUtils;
import com.foreverwin.mes.meapi.model.*;
import com.foreverwin.mes.meapi.service.*;
import com.foreverwin.mes.warehouse.constant.Constants;
import com.foreverwin.mes.warehouse.mapper.InventoryMoveLogMapper;
import com.foreverwin.mes.warehouse.model.InventoryMoveLog;
import com.foreverwin.mes.warehouse.service.InventoryMoveLogService;
import com.foreverwin.mes.warehouse.vo.InventoryMoveLogVo;
import com.sap.me.extension.Services;
import com.sap.me.frame.transitionutils.Exceptions;
import com.sap.me.inventory.InventoryConsumeRequest;
import com.sap.me.inventory.InventoryServiceInterface;
import org.assertj.core.util.Lists;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * <p>
 * 库存调拨记录 服务实现类
 * </p>
 *
 * @author Ervin Chen
 * @since 2020-02-18
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class InventoryMoveLogServiceImpl extends ServiceImpl<InventoryMoveLogMapper, InventoryMoveLog> implements InventoryMoveLogService {

    @Autowired
    private CustomFieldsService customFieldsService;
    @Autowired
    private InventoryMoveLogMapper inventoryMoveLogMapper;
    @Autowired
    private ReasonCodeService reasonCodeService;
    @Autowired
    private StorageLocationService storageLocationService;
    @Autowired
    private InventoryService inventoryService;
    @Autowired
    private ItemService itemService;
    @Autowired
    private InventoryAssyDataService inventoryAssyDataService;


    @Override
    public Page<InventoryMoveLog> selectPage(FrontPage<InventoryMoveLog> frontPage, InventoryMoveLog inventoryMoveLog) {
        EntityWrapper<InventoryMoveLog> queryWrapper = new EntityWrapper<>();
        queryWrapper.setEntity(inventoryMoveLog);
        return super.selectPage(frontPage.getPagePlus(), queryWrapper);
    }

    @Override
    public List<InventoryMoveLog> selectList(InventoryMoveLog inventoryMoveLog) {
        EntityWrapper<InventoryMoveLog> queryWrapper = new EntityWrapper<>();
        queryWrapper.setEntity(inventoryMoveLog);
        return super.selectList(queryWrapper);
    }

    @Override
    public List<ReasonCode> selectReasonCodeList() {
        String site = CommonMethods.getSite();
        CustomFields queryEntity = new CustomFields();
        queryEntity.setAttribute(Constants.ALLOCATION);
        queryEntity.setValue(Constants.ALLOCATION_Y);
        List<String> handles = customFieldsService.selectList(queryEntity)
                .stream()
                .map(customFields -> customFields.getHandle())
                .collect(Collectors.toList());

        if (handles.isEmpty()) return Lists.emptyList();
        EntityWrapper<ReasonCode> entityWrapper = new EntityWrapper<>();
        entityWrapper.eq("site", site);
        entityWrapper.in("handle", handles);
        return reasonCodeService.selectList(entityWrapper);
    }

    @Override
    public List<StorageLocation> selectStorageLocationList(String reasonCodeBo) {
        String site = CommonMethods.getSite();
        CustomFields queryEntity = new CustomFields();
        queryEntity.setHandle(reasonCodeBo);
        queryEntity.setAttribute(Constants.COMMIT_LOCATION);
        List<String> storageLocations = customFieldsService.selectList(queryEntity)
                .stream()
                .map(customFields -> customFields.getValue())
                .collect(Collectors.toList());

        if (storageLocations.isEmpty()) return Lists.emptyList();
        EntityWrapper<StorageLocation> entityWrapper = new EntityWrapper<>();
        entityWrapper.eq("site", site);
        entityWrapper.in("storage_location", storageLocations);
        return storageLocationService.selectList(entityWrapper);
    }

    @Override
    public InventoryMoveLogVo selectInventory(String reasonCodeBo, String inventoryId) {
        String site = CommonMethods.getSite();

        //检查库存是否存在
        if (StringUtils.isBlank(inventoryId)) {
            throw BusinessException.build("warehouse.inventoryMove.inventoryIdNotBlank", new Object[]{});
        }
        Inventory inventory = inventoryService.selectById(HandleEnum.INVENTORY.getHandle(site, inventoryId));
        if (inventory == null) {
            throw BusinessException.build("warehouse.inventoryMove.inventoryNotExist", inventoryId);
        }
        if (inventory.getQtyOnHand() <= 0) {
            throw BusinessException.build("warehouse.inventoryMove.inventory.qtyOnHandNotExist", inventoryId);
        }

        //检查原因代码物料类型
        String itemBo = inventory.getItemBo();
        CustomFields materialTypeField = customFieldsService.getAttributeValue(reasonCodeBo, Constants.ALLOCATION_ITEM_TYPE);
        if (materialTypeField == null) {
            throw BusinessException.build("warehouse.inventoryMove.reasonCode.allocationItemTypeNotExist", HandleEnum.REASON_CODE.getPart(reasonCodeBo, 1));
        }
        CustomFields _materialTypeField = customFieldsService.getAttributeValue(itemBo, Constants.MATERIAL_TYPE);
        if (_materialTypeField == null) {
            throw BusinessException.build("warehouse.inventoryMove.item.materialTypeNotExist", HandleEnum.REASON_CODE.getPart(itemBo, 1));
        }
        String materialType = materialTypeField.getValue();
        String _materialType = _materialTypeField.getValue();
        if (!Objects.equals(materialType, _materialType)) {
            throw BusinessException.build("warehouse.inventoryMove.inventoryNotMatchReasonCode", inventoryId, HandleEnum.REASON_CODE.getPart(reasonCodeBo, 1));
        }

        Item item = itemService.selectItem(itemBo);


        InventoryMoveLogVo inventoryMoveLogVo = new InventoryMoveLogVo();
        inventoryMoveLogVo.setInventoryId(inventoryId);
        inventoryMoveLogVo.setItemBo(itemBo);
        inventoryMoveLogVo.setItem(item.getItem());
        inventoryMoveLogVo.setItemDescription(item.getDescription());
        inventoryMoveLogVo.setUnitOfMeasure(item.getUnitOfMeasure());
        inventoryMoveLogVo.setQtyOnHand(inventory.getQtyOnHand());
        inventoryMoveLogVo.setQty(inventory.getQtyOnHand());
        if (!StringUtils.isBlank(inventory.getStorageLocationBo())) {
            inventoryMoveLogVo.setStorageLocation(HandleEnum.STORAGE_LOCATION.getPart(inventory.getStorageLocationBo(), 1));
        }


        InventoryAssyData queryEntity = new InventoryAssyData();
        queryEntity.setInventoryBo(inventory.getHandle());
        inventoryAssyDataService.selectList(queryEntity)
                .stream()
                .forEach(inventoryAssyData -> {
                    if (Constants.BATCH_NUMBER.equals(inventoryAssyData.getDataField())) {
                        inventoryMoveLogVo.setBatchNumber(inventoryAssyData.getDataAttr());
                    }
                    if (Constants.VENDOR_LOT.equals(inventoryAssyData.getDataField())) {
                        inventoryMoveLogVo.setVendorLot(inventoryAssyData.getDataAttr());
                    }
                });
        return inventoryMoveLogVo;
    }

    @Override
    public boolean insertOrUpdate(List<InventoryMoveLog> inventoryMoveLogs) {
        String site = CommonMethods.getSite();
        String userBo = CommonMethods.getUserBo();
        Date now = new Date();

        for (InventoryMoveLog inventoryMoveLog : inventoryMoveLogs) {
            String inventoryId = inventoryMoveLog.getInventoryId();
            String itemBo = inventoryMoveLog.getItemBo();
            Double qty = inventoryMoveLog.getQty();

            //校验字段
            validateFields(inventoryMoveLog);

            {
                //调研ERP原材料退库/半成品入库接口
            }

            //扣减ME库存
            InventoryServiceInterface inventoryServiceInterface = Services.getService("com.sap.me.inventory", "InventoryService", site);
            InventoryConsumeRequest consumeRequest = new InventoryConsumeRequest();
            consumeRequest.setInventoryRef(HandleEnum.INVENTORY.getHandle(site, inventoryId));
            consumeRequest.setComponentRef(itemBo);
            consumeRequest.setQty(BigDecimal.valueOf(qty));
            try {
                inventoryServiceInterface.consume(consumeRequest);
            } catch (com.sap.me.frame.domain.BusinessException e) {
                throw BusinessException.build(Exceptions.convert(e).toString());
            }

            //保存调拨记录
            inventoryMoveLog.setHandle(HandleEnum.INVENTORY_MOVE_LOG.getHandle(site, inventoryId, DateUtil.format(now)));
            inventoryMoveLog.setSite(site);
            inventoryMoveLog.setCreateUserBo(userBo);
            inventoryMoveLog.setCreatedDateTime(now);
            this.insert(inventoryMoveLog);
        }

        return true;
    }

    private boolean validateFields(InventoryMoveLog inventoryMoveLog) {
        String targetStorageLocation = inventoryMoveLog.getTargetStorageLocation();
        if (StringUtils.isBlank(targetStorageLocation)) {
            throw BusinessException.build("warehouse.inventoryMove.targetStorageLocationNotBlank", new Object[]{});
        }

        return true;
    }

}